﻿using System;
using System.Collections.Generic;
//using System.Linq;
using System.Text;
// add
using System.IO;
using System.Data;


namespace FormBaseLib
{
    public class CDatasetKeyValue : CBase, ICRUDRow
    {
        DataSetKeyValue mDataSetDB;
        DataSetKeyValue.TKeyValueDataTable mTableDB;
        DataSetKeyValue.TKeyValueRow mRowDB;  // as a cursor

        DataSetKeyValue mDataSetEntry;
        DataSetKeyValue.TKeyValueDataTable mTableEntry;
        public DataSetKeyValue.TKeyValueRow mRow { get; set; }
        DataSetKeyValue.TKeyValueRow mRowBackup;

        public DataView mDataView { get; private set; }
        public string msFile { get; set; }
        public CDatasetKeyValue()
        {
            myInit();
        }

        public bool Save()
        {
            if (string.IsNullOrEmpty(msFile))
            {
                SetLastError(enumErrorNo.ErrorEmptyOrNull, "Please input filename.");
                return false;
            }
            if (!Directory.Exists(Path.GetDirectoryName(msFile)))
            {
                SetLastError(enumErrorNo.ErrorNotExist, string.Format("Directory does not exist. File={0}.", msFile));
                return false;
            }
            File.WriteAllText(msFile, mDataSetDB.GetXml(), Encoding.UTF8);
            return true;
        }
        public bool SaveSchema(string sFile)
        {
            File.WriteAllText(sFile, mDataSetDB.GetXmlSchema().Replace("utf-16", "utf-8"), Encoding.UTF8);
            return true;
        }

        public bool Load()
        {
            //CProject.mLastError.ClearLastError();
            if (string.IsNullOrEmpty(msFile))
            {
                SetLastError(enumErrorNo.ErrorEmptyOrNull, string.Format("Please input filename."));
                return false;
            }
            if (!File.Exists(msFile))
            {
                SetLastError(enumErrorNo.ErrorNotExist, string.Format("File does NOT exist. File={0}.", msFile));
                return false;
            }
            mDataSetDB.Clear();

            XmlReadMode mode1 = mDataSetDB.ReadXml(msFile);
            if (mTableDB.Rows.Count < 1)
            {
                SetLastError(enumErrorNo.ErrorNotExist, String.Format("Rows count < 1 in file {0}.", msFile));
                return false;
            }
            return true;
        }
        private void myInit()
        {
            mDataSetDB = new DataSetKeyValue();
            mTableDB = mDataSetDB.TKeyValue;

            mDataSetEntry = new DataSetKeyValue();
            mTableEntry = mDataSetEntry.TKeyValue;
            mRow = mTableEntry.NewTKeyValueRow();
            mRowBackup = mTableEntry.NewTKeyValueRow();
            RowClear();
        }
        public void RowClear()
        {
            //DataSetKeyValue.TKeyValueRow RowBlank = mTableEntry.NewTKeyValueRow();
            //mRow.ItemArray = mTableEntry.NewTKeyValueRow().ItemArray;
            // Primary key can't be DBNull!
            //mRow.FKey = string.Empty;

            // DBNull fields will cause many problem on runtime!
            // so, we clear by setting the init value for each field.
            mRow.FKey = string.Empty;
            mRow.FValue = string.Empty;
        }
        public bool RowCreate(bool bCheck)
        {
            if (bCheck)
            {
                if (!RowCheckForCreate())
                    return false;

                if (RowFindPrimaryKey(mRow.FKey))
                {
                    SetLastError(enumErrorNo.ErrorExist, "Duplicated key=" + mRow.FKey);
                    return false;
                }
            }

            try
            {
                mRowDB = mTableDB.NewTKeyValueRow();
                RowFlush();
                mTableDB.AddTKeyValueRow(mRowDB);
            }
            catch (Exception ex)
            {
                SetLastError(ex.Message);
                return false;
            }
            if (!RowBackup())
                return false;

            return true;
        }
        public bool SearchDataView(string sRowFilter, string sSort)
        {
            try
            {
                mDataView = mTableDB.DefaultView;
                mTableDB.DefaultView.RowFilter = sRowFilter;
                mTableDB.DefaultView.Sort = sSort;
                return true;
            }
            catch (Exception ex)
            {
                SetLastError(ex.Message);
                return false;
            }
        }
        bool RowFetch()
        {
            if (mRowDB == null)
            {
                SetLastError("mRowDB == null in RowFetch().");
                return false;
            }

            mRow.ItemArray = mRowDB.ItemArray;
            RowBackup();
            return true;
        }
        public bool RowBackup()
        {
            if (mRowDB == null)
                return false;
            if (mRowBackup == null)
                return false;
            mRowBackup.ItemArray = mRowDB.ItemArray;
            return true;
        }
        bool RowFlush()
        {
            if (mRow == null)
                return false;

            mRowDB.ItemArray = mRow.ItemArray;
            return true;
        }

        public bool RowRestore()
        {
            // primary key can NOT be DBNull! But we can only test any other field here.
            if ((mRowBackup == null) || (mRowBackup.IsFValueNull()))
            {
                RowClear();
            }
            else
            {
                mRow.ItemArray = mRowBackup.ItemArray;
            }
            return true;
        }

        public bool RowRead(bool bCheck)
        {
            if (bCheck)
                if (!RowCheckForRead())
                    return false;

            DataRow[] rowsFind;
            string sFilter;
            try
            {
                sFilter = string.Format("FKey='{0}'", mRow.FKey);
                rowsFind = mTableDB.Select(sFilter);
                if (rowsFind.Length > 0)
                {
                    // the cursor
                    mRowDB = rowsFind[0] as DataSetKeyValue.TKeyValueRow;
                    //
                    if (!RowFetch())
                        return false;

                    return true;
                }
            }
            catch (Exception ex)
            {
                SetLastError(ex.Message);
                return false;
            }
            return false;
        }
        public bool RowCheckForCreate()
        {
            if (!RowCheckPrimaryKey())
                return false;

            return true;
        }
        public bool RowCheckForRead()
        {
            if (!RowCheckPrimaryKey())
                return false;

            return true;
        }
        public bool RowCheckForUpdate()
        {
            if (!RowCheckPrimaryKey())
                return false;

            if ((mRowDB == null) || (mRowDB.FKey == null))
            {
                SetLastError(enumErrorNo.WrongOperation, "Please query record first.");
                return false;
            }
            if (mRowDB.FKey != mRow.FKey)
            {
                SetLastError(enumErrorNo.ErrorChange, "Primary key can NOT be changed..");
                return false;
            }

            return true;
        }
        public bool RowCheckPrimaryKey()
        {
            if (mRow == null)
            {
                SetLastError("mRow == null.");
                return false;
            }
            if (string.IsNullOrEmpty(mRow.FKey))
            {
                SetLastError(enumErrorNo.ErrorEmptyOrNull, "Please input Primary Key.");
                return false;
            }
            return true;
        }

        public bool RowCheckForDelete()
        {
            if (!RowCheckPrimaryKey())
                return false;

            if ((mRowDB == null) || (mRowDB.FKey == null))
            {
                SetLastError(enumErrorNo.WrongOperation, "Please query record first.");
                return false;
            }
            if (mRowDB.FKey != mRow.FKey)
            {
                SetLastError(enumErrorNo.ErrorChange, "Primary key can NOT be changed..");
                return false;
            }

            return true;
        }

        public bool RowUpdate(bool bCheck)
        {
            if (bCheck)
            {
                if (!RowCheckForUpdate())
                    return false;

                if (!RowFindPrimaryKey(mRow.FKey))
                {
                    SetLastError(enumErrorNo.ErrorNotExist, "Not exist key=" + mRow.FKey);
                    return false;
                }

                // Verify dirty-read by check the whole row data or the field LastUpdateTime in last selected record.
                if (mRowDB.FValue != mRowBackup.FValue)  // verify by the whole row!  (or by timestamp)
                {
                    SetLastError(enumErrorNo.ErrorLock, "The last query record has been changed by other user.");
                    return false;
                }

            }
            if (!RowFlush())
                return false;

            if (!RowBackup())
                return false;

            return true;
        }
        public bool RowDelete(bool bCheck)
        {
            if (bCheck)
            {
                if (!RowCheckForDelete())
                    return false;

                if (!RowFindPrimaryKey(mRow.FKey))
                {
                    SetLastError(enumErrorNo.ErrorNotExist, "Not exist key=" + mRow.FKey);
                    return false;
                }

                // Verify dirty-read by check the whole row data or the field LastUpdateTime in last selected record.
                if (mRowDB.FValue != mRowBackup.FValue)  // verify by the whole row!  (or by timestamp)
                {
                    SetLastError(enumErrorNo.ErrorLock, "The last query record has been changed by other user.");
                    return false;
                }

            }

            try
            {
                mRowDB.Delete();
            }
            catch (Exception ex)
            {
                SetLastError(ex.Message);
                return false;
            }
            return true;
        }
        public bool RowFindPrimaryKey()
        {
            if (string.IsNullOrEmpty(mRow.FKey))
            {
                SetLastError(enumErrorNo.ErrorEmptyOrNull, "Please input key");
                return false;
            }
            try
            {
                if (mTableDB.Rows.Contains(mRow.FKey))
                    return true;
            }
            catch (Exception ex)
            {
                SetLastError(ex.Message);
                return false;
            }
            return false;
        }

        public bool RowFindPrimaryKey(string sKey)
        {
            mRow.FKey = sKey;
            return RowFindPrimaryKey();
        }

        public bool HasChanges()
        {
            return mDataSetDB.HasChanges();
        }
        public void DeleteAllRows()
        {
            mDataSetDB.Clear();
        }

    }
}
